package com.song.shiro.config;

import com.song.shiro.entity.Permission;
import com.song.shiro.entity.Role;
import com.song.shiro.entity.User;
import com.song.shiro.enums.UserStatusEnum;
import com.song.shiro.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AuthorizingRealm实现认证和授权
 */
@Component
public class MyAuthRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    /**
     * 执行授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取用户信息
        Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
        //通过用户名从数据库中查用户，获取用户角色，权限等信息
        String username = primaryPrincipal.toString();
        User user = userService.queryByUsername(username);
        List<Role> roles = new ArrayList<>();
        List<Permission> permissions = new ArrayList<>();
        if (user != null){
            roles = userService.queryRolesByUsername(username);
            permissions = userService.queryPermissionsByUsername(username);
        }
        List<String> roleList = roles.stream().map(Role::getJs).collect(Collectors.toList());
        List<String> permissionList = permissions.stream().map(Permission::getQx).collect(Collectors.toList());
        //实际使用中，登录用户信息一般存放在redis中
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRoles(roleList);
        authorizationInfo.addStringPermissions(permissionList);
        return authorizationInfo;
    }

    /**
     * 执行认证逻辑
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        User user = userService.queryByUsername(username);
        if (user == null){
            throw new UnknownAccountException("未知账号");
        }
        if (UserStatusEnum.JY.getZtdm().equals(user.getStatus())){
            throw new LockedAccountException("禁用账号");
        }
        String password = new String(token.getPassword());
        if (!user.getPassword().equals(password)){
            throw new CredentialsException("认证失败");
        }
        return new SimpleAuthenticationInfo(username, password, getName());
    }
}
